home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / DVIM72-Mac 1.9.6 / source / sillymalloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-14  |  8.5 KB  |  374 lines  |  [TEXT/R*ch]

  1. /*
  2.     sillymalloc.c  by James W. Walker, 1991
  3.     
  4.     This is a simple memory allocation scheme for DVIM72-Mac.
  5.     DVIM72-Mac allocates a whole bunch of small chunks of memory,
  6.     does some computation and printing, and frees all of the chunks.
  7.     Therefore no garbage collection is needed, we can essentially
  8.     allocate from a stack.
  9.     
  10.     Public routines:
  11.     
  12.     Ptr        sillymalloc( Size howmuch );
  13.     
  14.     This routine attempts to allocate "howmuch" memory.  Memory is first
  15.     allocated as nonrelocatable memory in the application heap, then
  16.     when that runs out we try to use MultiFinder temporary memory.
  17.     The latter is not strictly kosher; MultiFinder memory is supposed to
  18.     be so temporary that you don't process events while it's around.
  19.     If we can't get the memory, the result is NIL.
  20.     
  21.     void        sillyfree( void );
  22.     
  23.     This routine frees ALL of the memory allocated by sillymalloc.
  24.     
  25.     void        silly_get_MF_mem_status( void );
  26.     
  27.     This sets the variable MF_mem_status.
  28.  
  29.  */
  30.  
  31. #define    TRACE 0
  32.  
  33. #if TRACE
  34. #include <stdio.h>
  35. #include "TextDisplay.h"
  36. #endif
  37.  
  38. #include "sillymalloc.h"
  39.  
  40. extern Boolean TrapAvailable( short trapnum );
  41. extern void    Update_memory_indicators( void );
  42.  
  43. #ifndef NIL
  44. #define NIL 0L
  45. #endif
  46.  
  47. #define MIN_POOL          32000L
  48. #define RESERVE_MEM        60000L
  49.  
  50. #ifndef MAX
  51. #define MAX(a,b)  ((a)<(b) ? b : a)
  52. #endif
  53.  
  54.  
  55. typedef struct sillypool {
  56.     struct sillypool     *next;        /* Ptr to next pool */
  57.     Ptr                 freeplace;    /* Ptr to first free byte */
  58.     Handle                MF_handle;    /* handle if this is MF mem, else NIL */
  59.     Size                size;        /* How big is storage? */
  60.     char                 storage[];    /* start of actual free space */
  61. } sillypool;
  62.  
  63. static sillypool *top_pool = NIL;    /* Start of our list of pools. */
  64. static long reserve_heap;    /* leave some heap space for the driver, etc. */
  65. static long reserve_temp_mem;    // leave some multifinder memory for safety
  66. #if TRACE
  67. static long total_allocated;
  68. #endif
  69.  
  70. sm_temp_mem_status    MF_mem_status = sm_unknown;
  71.  
  72. /* prototypes of private routines */
  73. static sillypool    *sillynewpool( Size needed );
  74. static OSErr        growsillypool( Size newsize );
  75. void        silly_get_MF_mem_status( void );
  76.  
  77. #define        DEBUG        0
  78.  
  79. #if DEBUG
  80. #define        CKPT(x)        DebugStr( "\p" x ";hc" );
  81. #define        ASSERT(x,y)        if (!(x)) {DebugStr("\p" y);}
  82. #else
  83. #define        CKPT(x)
  84. #define        ASSERT(x,y)
  85. #endif
  86.  
  87.  
  88. /* ----------------------- sillyfree ------------------------------- */
  89. //    Free all memory pools.
  90. void sillyfree( void )
  91. {
  92.     register  sillypool *dead;
  93.     OSErr                err;
  94.  
  95. #if TRACE
  96.     TD_printf( "\ntotal allocated: %ld.", total_allocated );
  97. #endif
  98.     while (top_pool != NIL)
  99.     {
  100.         dead = top_pool;
  101. #if TRACE
  102.         TD_printf( "\nfree pool %ld, %ld in use.", dead->size,
  103.             dead->freeplace - StripAddress((Ptr)&dead->storage) );
  104. #endif
  105.         top_pool = top_pool->next;
  106.         if (dead->MF_handle == NIL)
  107.             DisposPtr( (Ptr) dead );
  108.         else
  109.             MFTempDisposHandle( dead->MF_handle, &err );
  110.     }
  111.     Update_memory_indicators();
  112. }
  113.  
  114.  
  115. /* ----------------------- sillymalloc ------------------------------- */
  116. Ptr sillymalloc( register Size howmuch )
  117. {
  118.     Ptr  newmem;
  119.     Size  shortage;
  120.     sillypool *newpool;
  121.     OSErr        err;
  122.  
  123.     CKPT("malloc begin");
  124.     howmuch = (howmuch + 1L) & 0xFFFFFFFE; /* round to next even number */
  125. #if TRACE
  126.     TD_printf( " (malloc %ld", howmuch );
  127. #endif
  128.     if (top_pool == NIL)    /* Get the first pool. */
  129.     {
  130. #if TRACE
  131.         total_allocated = 0L;
  132. #endif
  133.         if (MF_mem_status == sm_unknown)
  134.             silly_get_MF_mem_status();
  135.         top_pool = sillynewpool( howmuch );
  136.         if (top_pool == NIL)
  137.         {
  138. #if TRACE
  139.             TD_printf( " NIL pool)\n" );
  140. #endif
  141.             CKPT( "malloc NIL pool end" );
  142.             return NIL;
  143.         }
  144.         top_pool->next = NIL;
  145.     }
  146.     /* Now we have a non-null top pool. */
  147.     shortage = top_pool->freeplace + howmuch -
  148.         ( (Ptr)(top_pool->storage) + top_pool->size );
  149.     if (shortage > 0)
  150.     {    /* Not enuf room, try to grow pool */
  151.         err = growsillypool( MAX(shortage, MIN_POOL) );
  152.         if (err != noErr)    /* Can't grow, try for another. */
  153.         {
  154.             newpool = sillynewpool( howmuch );
  155.             if (newpool == NIL)
  156.             {
  157. #if TRACE
  158.                 TD_printf( " NIL pool)\n" );
  159. #endif
  160.                 CKPT("malloc NIL end");
  161.                 return NIL;
  162.             }
  163.             newpool->next = top_pool;
  164.             top_pool = newpool;
  165.         }
  166.     }
  167.     newmem = top_pool->freeplace;
  168.     top_pool->freeplace += howmuch;
  169.     ASSERT( top_pool->freeplace <= (Ptr)top_pool->storage + top_pool->size,
  170.         "malloc fail sanity check" );
  171. #if TRACE
  172.     total_allocated += howmuch;
  173.     TD_printf( ")\n" );
  174. #endif
  175.     CKPT("malloc good end");
  176.     return newmem;
  177. }
  178.  
  179. /* 
  180.     Private routine to allocate a new memory pool.
  181. */
  182. /* ----------------------- sillynewpool ------------------------------- */
  183. static sillypool    *sillynewpool( Size needed )
  184. {
  185.     sillypool    *pool;
  186.     Handle        MF_temp;
  187.     OSErr        err;
  188.     Size        this_much;
  189.     
  190.     CKPT("newpool begin");
  191.     this_much = MAX( needed + sizeof(sillypool), MIN_POOL );
  192. #if TRACE
  193.     TD_printf( " (newpool %ld, %ld", needed, this_much );
  194. #endif
  195.     if (this_much + reserve_heap < FreeMem())
  196.     {
  197.         pool = (sillypool *) NewPtr( this_much );
  198. #if TRACE
  199.         if (pool == NIL)
  200.             TD_printf( " NewPtr failed" );
  201.         else if (MemError() != noErr)
  202.             TD_printf( " NewPtr error" );
  203.         else
  204.             TD_printf( " from app heap" );
  205. #endif
  206.         ASSERT( (pool == NIL) || (MemError() != noErr), "NewPtr error" );
  207.     }
  208.     else
  209.     {
  210.         pool = NIL;
  211.     }
  212.  
  213.     if (pool == NIL)
  214.     {
  215.         if ( (MF_mem_status == sm_no_temp_mem) ||
  216.             (this_much + reserve_temp_mem > MFFreeMem()) )
  217.         {
  218. #if TRACE
  219.             TD_printf( " no temp mem)\n" );
  220. #endif
  221.             CKPT( "newpool NIL end" );
  222.             return NIL;
  223.         }
  224.         MF_temp = MFTempNewHandle( this_much, &err );
  225.         ASSERT( (MF_temp == NIL) || (err != noErr),
  226.             "MFTempNewHandle error" );
  227.         if (MF_temp == NIL)
  228.         {
  229. #if TRACE
  230.             TD_printf( " temp new failed)\n" );
  231. #endif
  232.             CKPT("newpool NIL end");
  233.             return NIL;
  234.         }
  235. #if TRACE
  236.         else if (err != noErr)
  237.             TD_printf( " temp new error %d", err );
  238.         else
  239.             TD_printf( " from temp mem" );
  240. #endif
  241.         MFTempHLock( MF_temp, &err );
  242. #if TRACE
  243.         if (err != noErr)
  244.             TD_printf( " temp lock error %d", err );
  245. #endif
  246.         ASSERT( (MF_temp == NIL) || (err != noErr),
  247.             "MFTempHLock error" );
  248.         pool = (sillypool *) *MF_temp;
  249.         pool->MF_handle = MF_temp;
  250.     }
  251.     else
  252.         pool->MF_handle = NIL;
  253.     pool = (sillypool *) StripAddress( (Ptr) pool );
  254.     pool->freeplace = (Ptr) (pool->storage);
  255.     pool->size = this_much - sizeof(sillypool);
  256.     Update_memory_indicators();
  257. #if TRACE
  258.     TD_printf( ")\n" );
  259. #endif
  260.     CKPT("newpool good end");
  261.     return pool;
  262. }
  263.  
  264.  
  265. /* ----------------------- growsillypool ------------------------------- */
  266. static OSErr        growsillypool( Size more )
  267. {
  268.     OSErr    err;
  269.     Size    new_size;
  270.     THz        save_zone;
  271.     
  272.     CKPT("growpool begin");
  273.     new_size = sizeof(sillypool) + top_pool->size + more;
  274. #if TRACE
  275.     TD_printf( " (grow %ld to %ld", more, new_size );
  276. #endif
  277.     if (top_pool->MF_handle != NIL)
  278.     {
  279.         if (MF_mem_status == sm_temp_mem_is_real)
  280.         {
  281.             save_zone = GetZone();
  282.             SetZone( HandleZone( top_pool->MF_handle ) );
  283.             SetHandleSize( top_pool->MF_handle, new_size );
  284.             err = MemError();
  285.             SetZone( save_zone );
  286.             if (err == noErr)
  287.             {
  288. #if TRACE
  289.                 TD_printf( " SetHandleSize OK" );
  290. #endif
  291.                 top_pool->size = top_pool->size + more;
  292.             }
  293. #if TRACE
  294.             else
  295.                 TD_printf( " SetHandleSize error %d", err );
  296. #endif
  297.         }
  298.         else
  299.             err = memFullErr;    /* Can't resize MF temporary memory. */
  300.     }
  301.     else
  302.     {
  303.         if (more + reserve_heap < FreeMem())
  304.         {
  305.             SetPtrSize( (Ptr)top_pool, new_size );
  306.             err = MemError();
  307.             if (err == noErr)
  308.             {
  309.                 top_pool->size = top_pool->size + more;
  310. #if TRACE
  311.                 TD_printf( " SetPtrSize OK" );
  312. #endif
  313.             }
  314. #if TRACE
  315.             else
  316.                 TD_printf( " SetPtrSize error %d", err );
  317. #endif
  318.         }
  319.         else
  320.             err = memFullErr; /* not enuf room to resize */
  321.     }
  322.     Update_memory_indicators();
  323. #if TRACE
  324.     TD_printf( ")\n" );
  325. #endif
  326.     CKPT("growpool end");
  327.     return err;
  328. }
  329.  
  330. #ifndef OSDISPATCH
  331. #define OSDISPATCH        0xA88F
  332. #endif
  333.  
  334. #ifndef GESTALT
  335. #define GESTALT            0xA1AD
  336. #endif
  337. /* ------------------------ silly_get_MF_mem_status ------------------- */
  338. void        silly_get_MF_mem_status( void )
  339. {
  340.     long    response;
  341.     OSErr    err;
  342.     long    **reserve_heap_h, **reserve_temp_mem_h;
  343.     
  344.     MF_mem_status = TrapAvailable( OSDISPATCH ) ?
  345.         sm_temp_mem : sm_no_temp_mem;
  346. #if TRACE
  347.     if (MF_mem_status == sm_temp_mem)
  348.         TD_printf( " (temp mem is available" );
  349. #endif
  350.     
  351.     if ( TrapAvailable(GESTALT) )
  352.     {
  353.         err = Gestalt( gestaltOSAttr, &response );
  354.         if ( (err == noErr) && (response & (1L << gestaltRealTempMemory)) )
  355.             MF_mem_status = sm_temp_mem_is_real;
  356. #if TRACE
  357.         if (MF_mem_status == sm_temp_mem_is_real)
  358.             TD_printf( " and real" );
  359. #endif
  360.     }
  361.     
  362.     reserve_heap_h = (long **) GetNamedResource( 'LONG', "\pheap reserve" );
  363.     if (reserve_heap_h != NIL)
  364.         reserve_heap = **reserve_heap_h;
  365. #if TRACE
  366.     else
  367.         TD_printf(" (heap reserve resource missing)" );
  368.     TD_printf( ")\n" );
  369. #endif
  370.     reserve_temp_mem_h = (long **)GetNamedResource('LONG', "\pMF mem reserve" );
  371.     if (reserve_temp_mem_h != NIL)
  372.         reserve_temp_mem = **reserve_temp_mem_h;
  373. }
  374.